package com.dd.cloud.common.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseCookie;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;

/**
 * Cookie 工具类
 */
@Slf4j
public final class CookieUtils {

    /**
     * 得到Cookie的值, 不编码
     *
     * @param request
     * @param cookieName
     * @return
     */
    public static String getCookieValue(HttpServletRequest request, String cookieName) {
        return getCookieValue(request, cookieName, null);
    }

    /**
     * 得到Cookie的值,
     *
     * @param request
     * @param cookieName
     * @return
     */
    public static String getCookieValue(HttpServletRequest request, String cookieName, String charset) {
        Cookie[] cookieList = request.getCookies();
        if (cookieList == null || cookieName == null) {
            return null;
        }
        String retValue = null;
        try {
            for (Cookie cookie : cookieList) {
                if (cookie.getName().equals(cookieName)) {
                    if (charset != null && charset.length() > 0) {
                        retValue = URLDecoder.decode(cookie.getValue(), charset);
                    } else {
                        retValue = cookie.getValue();
                    }
                    break;
                }
            }
        } catch (UnsupportedEncodingException e) {
            log.error("Cookie Decode Error.", e);
        }
        log.error("Cookie Decode value:{}", retValue);
        return retValue;
    }

    /**
     * 设置一个cookie
     *
     * @param response HttpServletResponse
     * @param name     cookie的名称
     * @param value    cookie的内容
     * @param maxAge   cookie的持续时间
     */
    public static void set(HttpServletResponse response,
                           String name,
                           String value,
                           int maxAge) {
        Cookie cookie = new Cookie(name, value);
        cookie.setPath("/");
        cookie.setMaxAge(maxAge);
        response.addCookie(cookie);
    }

    public static CookieBuilder newBuilder(HttpServletResponse response) {
        return new CookieBuilder(response);
    }

    public static class CookieBuilder {
        private HttpServletRequest request;
        private HttpServletResponse response;
        private Integer maxAge;
        private String charset;
        private boolean httpOnly = false;

        public CookieBuilder(HttpServletResponse response) {
            this.response = response;
        }

        //防跨域访问
        public CookieBuilder request(HttpServletRequest request) {
            this.request = request;
            return this;
        }

        //最大生命周期
        public CookieBuilder maxAge(int maxAge) {
            this.maxAge = maxAge;
            return this;
        }

        //设置格式
        public CookieBuilder charset(String charset) {
            this.charset = charset;
            return this;
        }

        //禁用JS访问
        public CookieBuilder httpOnly() {
            this.httpOnly = true;
            return this;
        }

        //构建
        public void build1(String cookieName, String cookieValue) {

            try {
                if (StringUtils.isBlank(charset)) {
                    charset = "utf-8";
                }

                if (cookieValue == null) {
                    cookieValue = "";
                } else if (StringUtils.isNotBlank(charset)) {
                    cookieValue = URLEncoder.encode(cookieValue, charset);
                }
                Cookie cookie = new Cookie(cookieName, cookieValue);
                if (maxAge != null && maxAge > 0) {
                    cookie.setMaxAge(maxAge);
                }
                if (null != request)// 设置域名的cookie
                {
                    cookie.setDomain(getDomainName(request));
                }
                cookie.setPath("/");
                cookie.setHttpOnly(httpOnly);
                response.addCookie(cookie);
            } catch (Exception e) {
                log.error("Cookie Encode Error.", e);
            }
        }

        //构建
        public void build(String cookieName, String cookieValue, String sameSite) {
            if (StringUtils.isBlank(sameSite)){
                build1(cookieName, cookieValue);
                return;
            }
            try {
                if (StringUtils.isBlank(charset)) {
                    charset = "utf-8";
                }

                if (cookieValue == null) {
                    cookieValue = "";
                } else if (StringUtils.isNotBlank(charset)) {
                    cookieValue = URLEncoder.encode(cookieValue, charset);
                }
                ResponseCookie cookie;
                if (maxAge != null && maxAge > 0) {
                    cookie = ResponseCookie.from(cookieName, cookieValue) // key & value
                            .httpOnly(httpOnly)        // 禁止js读取
                            .secure(true)        // 在http下也传输
                            .domain(getDomainName(request))// 域名
                            .maxAge(maxAge)
                            .path("/")            // path
                            .sameSite(sameSite)    // 大多数情况也是不发送第三方 Cookie，但是导航到目标网址的 Get 请求除外
                            .build()
                    ;
                } else {
                    cookie = ResponseCookie.from(cookieName, cookieValue) // key & value
                            .httpOnly(httpOnly)        // 禁止js读取
                            .secure(true)        // 在http下也传输
                            .domain(getDomainName(request))// 域名
                            .path("/")            // path
                            .sameSite(sameSite)    // 大多数情况也是不发送第三方 Cookie，但是导航到目标网址的 Get 请求除外
                            .build()
                    ;
                }

                // 设置Cookie Header
                response.setHeader(HttpHeaders.SET_COOKIE, cookie.toString());
            } catch (Exception e) {
                log.error("Cookie Encode Error.", e);
            }
        }

        /**
         * 得到cookie的域名
         */
        private String getDomainName(HttpServletRequest request) {
            String domainName;
            String serverName = request.getRequestURL().toString();
            if (serverName == null || serverName.equals("")) {
                domainName = "";
            } else {
                serverName = serverName.toLowerCase();
                serverName = serverName.substring(7);
                final int end = serverName.indexOf("/");
                serverName = serverName.substring(0, end);
                final String[] domains = serverName.split("\\.");
                int len = domains.length;
                if (len > 3) {
                    // www.xxx.com.cn
                    domainName = domains[len - 3] + "." + domains[len - 2] + "." + domains[len - 1];
                } else if (len <= 3 && len > 1) {
                    // xxx.com or xxx.cn
                    domainName = domains[len - 2] + "." + domains[len - 1];
                } else {
                    domainName = serverName;
                }
                if (serverName.matches("\\d+\\.\\d+\\.\\d+\\.\\d+")) {
                    domainName = serverName;
                }
            }
            if (domainName != null && domainName.indexOf(":") > 0) {
                String[] ary = domainName.split("\\:");
                domainName = ary[0];
            }
            return domainName;
        }
    }

    /**
     * 识别当前请求环境是PC还是移动端
     *
     * @param requestHeader
     * @return true:移动端  false:pc
     */
    public static boolean isMobileDevice(String requestHeader) {
        /**
         * android : 所有android设备
         * mac os : iphone ipad
         * windows phone:Nokia等windows系统的手机
         */
        String[] deviceArray = new String[]{"android", "mac os", "windows phone"};
        if (requestHeader == null) {
            return false;
        }
        requestHeader = requestHeader.toLowerCase();
        for (int i = 0; i < deviceArray.length; i++) {
            if (requestHeader.indexOf(deviceArray[i]) > 0) {
                return true;
            }
        }
        return false;
    }
}